package com.pet_service.config;

import ch.qos.logback.core.util.StringUtil;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.pet_service.entity.User;
import com.pet_service.mapper.UserMapper;
import com.pet_service.util.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * 自定义token认证过滤器
 */
@Slf4j
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    private static final String SECRET = "mySecret";
    private static final String ISSUER = "pet_service";
    //不需要认证的接口
    //private static final String[] PASSLIST = {"/login", "/logout", "/images/**", "/test/**"};
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    //传入token认证失败处理器
    private TokenAuthenticationEntryPoint tokenAuthenticationEntryPoint;

    //有参构造方法
    public TokenAuthenticationFilter(TokenAuthenticationEntryPoint tokenAuthenticationEntryPoint) {
        this.tokenAuthenticationEntryPoint = tokenAuthenticationEntryPoint;
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException{

        try {
            //1.获取请求头的 token
            String header = request.getHeader("token");
            log.info("header={}", header);
            //2.判断是否需要认证
            if (StringUtil.isNullOrEmpty(header)) {
                //放行执行下一个过滤器 UsernamePasswordAuthenticationFilter
                filterChain.doFilter(request, response);
            } else {
                //3.验证token值
                DecodedJWT jwt = null;
                try {
                    jwt = JwtUtil.verifyToken(header, SECRET, ISSUER);
                } catch (JWTVerificationException e) {
                    throw new BadCredentialsException("jwt token认证失败!");
                }
                log.info("jwt={}", jwt);
                if(jwt == null){
                    throw new BadCredentialsException("jwt token认证失败!");
                }
                // 从token中获取用户信息
                String username = JwtUtil.getClaimAsString(header, SECRET, ISSUER, "username");
                log.info("解析token获取username={}", username);
                //根据用户名获取用户详细信息
                User user = userMapper.selectByUsername(username);
                log.info("根据用户名获取用户详细信息={}", user);
                //创建认证对象
                //参数1：用户名
                //参数2：密码
                //参数3：权限
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(username, null,
                                customUserDetailsService.getSysUserAuthority(user.getId()));
                //将这个对象交给认证管理器 AuthenticationManager
                SecurityContextHolder.getContext().setAuthentication(authentication);
                //放行执行下一个过滤器
                filterChain.doFilter(request, response);
            }
        }catch (BadCredentialsException e){
            tokenAuthenticationEntryPoint.commence(request, response, e);
        }

    }
}
